Read counts data

Load and transpose counts file (Sample IDs as header and miRNA IDs as first column)

oriCountsFile <- read.csv(file = paste(sep="", data_path,'/mature_counts_all.csv'))
countsFile <- as.data.frame(t(oriCountsFile)) # transpose oriCountsFile
countsFile <- janitor::row_to_names(countsFile, row_number=1)
countsFile <- tibble::rownames_to_column(countsFile, var="miR")
countsFile$miR <- chartr('.', '-', countsFile$miR) # replace '.' with '-' in miR
countsFile

Update the IDs

Fetch the mirbase22 IDs and sequences

mrbse <- read.table(mirbaseFile, header = T, sep = "\t")
mrbse <- mrbse[-c(1,2),] # The first two rows don't match up with mirbase, are the only duplicates, and are the only sequences with T's for some reason. I'll remove them.
dim(mrbse)
[1] 2656    2
head(mrbse)

Create microRNA Mapping table and Update Countfile miRNA Row Names

mrbse2 <- merge(mrbse, update, by.x = 1, by.y = 2, all.x = F, all.y = T)
mrbse2 <- mrbse2[,-4]
dim(mrbse2)
[1] 193   3
head(mrbse2)
rownames(mrbse2)<- mrbse2[,"OriginalName"]
rownames(countsFile)<-countsFile[,1]
rownames(countsFile)<- mrbse2[rownames(countsFile), "Name"]

Create Row for each miRNA and Merge this with the data

mergedData <- matrix(0, nrow = dim(mrbse)[1], ncol= 302)
mergedData <- data.frame(mergedData)
mergedData<- cbind(mrbse, mergedData)
colnames(mergedData)<- c("Name", "Seq", colnames(countsFile)[-1])
rownames(mergedData)<-mergeData[,1]
mergedData[rownames(countsFile), colnames(countsFile)[-1]]<- countsFile[,-1]
#mergedData <- merge(mrbse2, countsFile, by.x = 3, by.y = 1, all.x = T, all.y = F)
dim(mergedData)
[1] 2656  304
head(mergedData)
#mergedData <- mergedData[,-1] # Remove the original (old) IDs
mergedData[1:5,1:5]
mergedData
NA

Quintize the data

For each column: assign each miRNA a value 1-5 depending on which of the 20th percentiles it falls into. If the value is 0, it remains a 0

# Given a column, assign a number to each element from 0-5. All
# 0s get a 0, and the rest get a value according to the 20th percentile
# that it falls in among the non-zero values.
quintize <- function(vec) {
  qntls <- c(0, quantile(vec[which(vec != 0)], 0.2*(1:4)))
  vec2 <- sapply(vec, function(x) {
    if (x == 0) return(0)
    else return(max(which(x > qntls)))
  })
  return(vec2)
}
mergedData[,3:ncol(mergedData)] = lapply(mergedData[,3:ncol(mergedData)], FUN = function(y){as.numeric(y)})
dim(mergedData)
[1] 2656  304
quintizedData <- apply(mergedData[,-c(1:2)], 2, quintize)
quintizedData <- cbind(mergedData[,1:2], quintizedData)
quintizedData[1:5,1:5]
dim(quintizedData)
[1] 2656  304

Combine the replicates

Get the meta information

meta <- read.table(paste(sep="", data_path,"/meta_celltype_tissue_sRNA.txt"), header = T, sep = "\t")
meta$Sample_ID <- gsub("BioSample: https://www.ncbi.nlm.nih.gov/biosample/", "", meta$X.Sample_relation) # extract only SAMN IDs from X.Sample_relation
meta

Create Disease, Tissue, and Group (Tissue_Disease) columns

meta$Tissue <- str_replace_all(meta$X.Sample_source_name_ch1, " tissue", "")
meta$Tissue <- str_replace_all(meta$Tissue, "[^A-Za-z0-9]+", "\\.")
meta$Tissue <- str_replace_all(meta$Tissue, "\\.donor\\.[0-9]+", "")
meta$Tissue <- str_replace_all(meta$Tissue, "-", ".")
meta$Tissue <- str_replace_all(meta$Tissue, " ", ".")
meta$Tissue <- tolower(meta$Tissue)
meta$Tissue <- str_replace_all(meta$Tissue, "cb.cd34.lin.", "cb.cd34.lin")
meta$Disease <- "" #all normal
meta$Group <- apply(meta[,c(ncol(meta)-1,ncol(meta))], 1, function(x) paste(x[1], x[2], sep="_"))
meta$Group <- str_replace_all(meta$Group, "_", "")
head(meta)

Grouping: Combine replicates (samples that have the same type)

uniqueTissues <- unique(meta$Group)
meta$Sample_ID %in% names(quintizedData)
  [1]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [24]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [47]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [70]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [93]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[116]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[139]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[162]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[185]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
meta <- meta[!(meta$Sample_ID == "SAMN13014236"),] # Sample does not exist in counts file

# Remove columns in quintizedData that does not exist in meta (that means the sample type is not tissue and not cell type)
names(quintizedData) %in% meta$Sample_ID
  [1] FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [24] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
 [47] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [70] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE
 [93]  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE
[116]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[139]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
[162]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[185]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[208]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[231]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[254]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
[277]  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE
[300]  TRUE  TRUE  TRUE  TRUE FALSE
quintizedData2 <- quintizedData[,colnames(quintizedData) %in% meta$Sample_ID]

# Add Name and Seq columns
quintizedData2 <- cbind(quintizedData[,1:2], quintizedData2)


#quintizedData2 <- cbind(quintizedData$Seq,quintizedData2)
#quintizedData2 <- cbind(quintizedData$Name,quintizedData2)
#names(quintizedData2)[1] <- "Name"
#names(quintizedData2)[2] <- "Seq"
#names(quintizedData2) %in% meta$Sample_ID




combinedData <- lapply(uniqueTissues, function(x) {
  df <- as.data.frame(quintizedData2[,meta$Sample_ID[which(meta$Group == x)]])
  return(rowMeans(df))
})
names(combinedData) <- uniqueTissues
combinedData <- do.call(cbind, combinedData)
combinedData <- cbind(quintizedData2[,1:2], combinedData)
dim(combinedData)
[1] 2656  206

Ensure the terms are standardized

Ensure that all the group names appear in the ontology or the corrections file.

Get the ontology and correction files

ont <- read.table(paste(sep="", generaldata_path,"/ontology.txt"), header = F, sep = "\t")
corr <- read.table(paste(sep="", generaldata_path,"/corrections.txt"), header = T, sep = "\t")
head(ont)

Aim to have 0 as a result, meaning all terms are either already in the ontology or the correction file. Or else: update correction file or ontology file, or both.

trms <- unique(unlist(strsplit(names(combinedData)[3:ncol(combinedData)], "_"))) # Splits the composite terms that contain both tissue+disease
if (length(which(trms %in% union(corr[,1], unique(unlist(ont[,c(1,3)]))))) != 0){
  trms[-which(trms %in% union(corr[,1], unique(unlist(ont[,c(1,3)]))))] # Which terms aren't in the ontology or the corrected terms
} else {
  trms
}
character(0)

Correct current terms that need to be corrected.

colnames(combinedData) <- sapply(colnames(combinedData), function(z) {
  y <- strsplit(z, "_")[[1]]
  retVal <- sapply(y, function(x) {
    if (x %in% corr$currentTerm) {
      return(corr$correctedTerm[match(x, corr$currentTerm)])
    } else {
      return(x)
    }
  })
  return(paste(retVal, collapse = "_"))
})
dim(combinedData)
[1] 2656  206
head(combinedData)

Convert to long format

Add the Canonical column and Source column

n<-dim(combinedData)[1]
data<- cbind(combinedData["Name"],combinedData["Seq"],Canonical=rep(T, n) , Source=rep("Lorenzi*", n) , combinedData[,3:dim(combinedData)[2] ])
colnames(data)<- c("Name", "Seq", "Canonical", "Source", colnames(combinedData)[-c(1,2)])

#data <- combinedData # all tissues have to exist in ontology or correction files
#data$Canonical <- T
#data$Source <- "Lorenzi*"
#data <- data[,c(1,2,ncol(data)-1,ncol(data),3:(ncol(data)-2))] # Set columns alignment

colnames(data)
  [1] "Name"                                           "Seq"                                           
  [3] "Canonical"                                      "Source"                                        
  [5] "alveolar.macrophage"                            "monocyte"                                      
  [7] "immature.monocyte.derived.dendritic.cell"       "mature.monocyte.derived.dendritic.cell"        
  [9] "brain.vascular.smooth.muscle.cell"              "brain.vascular.adventitial.fibroblast"         
 [11] "brain.vascular.pericyte"                        "choroid.plexus.epithelial.cell"                
 [13] "choroid.plexus.fibroblast"                      "meningeal.cell"                                
 [15] "neuron"                                         "oligodendrocyte.precursor.cell"                
 [17] "schwann.cell"                                   "perineurial.cell"                              
 [19] "astrocyte"                                      "cerebellar.astrocyte"                          
 [21] "spinal.cord.astrocyte"                          "hippocampal.astrocyte"                         
 [23] "astrocytes.brain.stem"                          "midbrain.astrocyte"                            
 [25] "retinal.astrocyte"                              "dermal.microvascular.endothelial.cell"         
 [27] "dermal.lymphatic.endothelial.cell"              "keratinocyte"                                  
 [29] "keratinocyte"                                   "keratinocyte"                                  
 [31] "epidermal.melanocyte"                           "epidermal.melanocyte"                          
 [33] "epidermal.melanocyte"                           "epidermal.melanocyte"                          
 [35] "fibroblast.of.dermis"                           "fibroblast.of.dermis"                          
 [37] "fibroblast.of.dermis"                           "fibroblast.of.dermis"                          
 [39] "hair.dermal.papilla"                            "hair.germinal.matrix"                          
 [41] "hair.follicular.sheath.outer.root"              "hair.follicular.sheath.inner.root"             
 [43] "hair.follicular.keratinocyte"                   "lymphatic.endothelial.cell"                    
 [45] "lymphatic.fibroblast"                           "tonsil.endothelial.cell"                       
 [47] "tonsil.epithelial.cell"                         "tonsil.fibroblast"                             
 [49] "oral.keratinocyte"                              "gingival.fibroblast"                           
 [51] "periodontal.ligament.fibroblast"                "esophageal.smooth.muscle.cell"                 
 [53] "esophageal.epithelial.cell"                     "esophageal.fibroblast"                         
 [55] "gastric.smooth.muscle.cell"                     "intestinal.smooth.muscle.cell"                 
 [57] "intestinal.fibroblast"                          "colonic.microvascular.endothelial.cell"        
 [59] "colonic.smooth.muscle.cell"                     "colonic.epithelial.cell"                       
 [61] "rectal.smooth.muscle.cell"                      "pulmonary.microvascular.endothelial.cell"      
 [63] "pulmonary.artery.endothelial.cell"              "pulmonary.artery.smooth.muscle.cell"           
 [65] "pulmonary.artery.fibroblast"                    "pulmonary.alveolar.epithelial.cell"            
 [67] "bronchial.epithelial.cell"                      "tracheal.epithelial.cell"                      
 [69] "small.airway.epithelial.cell"                   "fibroblast.of.lung"                            
 [71] "fibroblast.of.lung"                             "bronchial.smooth.muscle.cell"                  
 [73] "tracheal.smooth.muscle.cell"                    "skeletal.muscle.cell"                          
 [75] "skeletal.muscle.satellite.cell"                 "skeletal.muscle.myoblast"                      
 [77] "adrenal.microvascular.endothelium"              "adrenal.cortical.cell"                         
 [79] "adrenal.gland.fibroblast"                       "thyroid.fibroblast"                            
 [81] "pancreatic.stellate.cell"                       "thymus.fibroblast"                             
 [83] "renal.glomerular.endothelial.cell"              "renal.proximal.tubular.epithelial.cell"        
 [85] "renal.cortical.epithelial.cell"                 "renal.epithelial.cell"                         
 [87] "renal.mesangial.cell"                           "bladder.microvascular.endothelial.cell"        
 [89] "bladder.smooth.muscle.cell"                     "urothelial.cell"                               
 [91] "prostate.microvascular.endothelial.cell"        "prostate.epithelial.cell"                      
 [93] "prostate.fibroblast"                            "seminal.vesicle.microvascular.endothelial.cell"
 [95] "seminal.vesicle.epithelial.cell"                "seminal.vesicle.fibroblast"                    
 [97] "calvarial.osteoblast"                           "femural.osteoblast"                            
 [99] "synoviocyte"                                    "nucleus.pulposus.cell"                         
[101] "annulus.pulposus.cell"                          "hepatic.sinusoidal.endothelial.cell"           
[103] "hepatocyte"                                     "hepatic.stellate.cell"                         
[105] "gall.bladder.fibroblast"                        "splenic.endothelial.cell"                      
[107] "splenic.fibroblast"                             "cardiac.microvascular.endothelial.cell"        
[109] "coronary.artery.endothelial.cell"               "aortic.endothelial.cell"                       
[111] "aortic.smooth.muscle.cell"                      "aortic.fibroblast"                             
[113] "cardiac.muscle.fibre"                           "cardiac.myocyte"                               
[115] "cardiac.fibroblast"                             "cardiac.ventricle.fibroblast"                  
[117] "cardiac.atrium.fibroblast"                      "fibroblast.of.cardiac.tissue"                  
[119] "cardiac.atrium.fibroblast"                      "pericardial.fibroblast"                        
[121] "corneal.epithelial.cell"                        "keratocyte"                                    
[123] "retinal.pigment.epithelial.cell"                "lens.epithelial.cell"                          
[125] "iris.pigment.epithelial.cell"                   "fibroblast.of.the.conjunctiva"                 
[127] "non.pigment.ciliary.epithelial.cell"            "trabecular.meshwork.cell"                      
[129] "choroid.fibroblast"                             "myometrial.microvascular.endothelial.cell"     
[131] "endometrial.microvascular.endothelial.cell"     "myometrial.smooth.muscle.cell"                 
[133] "amniotic.epithelial.cell"                       "villous.trophoblast"                           
[135] "fibroblast.of.villous.mesenchyme"               "amniotic.mesenchymal.stromal.cell"             
[137] "chorionic.mesenchymal.stromal.cell"             "adipose.microvascular.endothelial.cell"        
[139] "preadipocyte.visceral"                          "subcutaneous.preadipocyte"                     
[141] "ovarian.microvascular.endothelial.cell"         "ovarian.surface.epithelial.cell"               
[143] "ovarian.fibroblast"                             "mesenchymal.stem.cell.of.the.bone.marrow"      
[145] "mesenchymal.stem.cell.adipose"                  "hepatic.mesenchymal.stem.cell"                 
[147] "mesenchymal.stem.cell.of.umbilical.cord"        "pulmonary.mesenchymal.stem.cell"               
[149] "vertebral.mesenchymal.stem.cell"                "mammary.endothelial.cell"                      
[151] "mammary.epithelial.cell"                        "mammary.fibroblast"                            
[153] "umbilical.vein.endothelial.cell"                "umbilical.artery.endothelial.cell"             
[155] "umbilical.vein.smooth.muscle.cell"              "umbilical.artery.smooth.muscle.cell"           
[157] "hematopoietic.stem.cell"                        "t.lymphocyte.cd3"                              
[159] "monocyte.cd14"                                  "NK.cells"                                      
[161] "b.lymphocyte.cd19"                              "brain.microvascular.endothelial.cell"          
[163] "articular.chondrocyte"                          "ileum"                                         
[165] "jejunum"                                        "duodenum"                                      
[167] "right.colon"                                    "distal.colon"                                  
[169] "esophagus"                                      "trachea"                                       
[171] "vena.cava"                                      "pericardium"                                   
[173] "left.atrium"                                    "left.ventricle"                                
[175] "right.atrium"                                   "right.ventricle"                               
[177] "oviduct"                                        "thyroid.gland"                                 
[179] "uterus"                                         "lymph.node"                                    
[181] "placenta"                                       "breast"                                        
[183] "pancreas"                                       "adipose.tissue"                                
[185] "liver"                                          "brain"                                         
[187] "thymus"                                         "heart"                                         
[189] "lung"                                           "spleen"                                        
[191] "testis"                                         "ovary"                                         
[193] "kidney"                                         "skeletal.muscle"                               
[195] "small.intestine"                                "colon"                                         
[197] "prostate.gland"                                 "bladder"                                       
[199] "uterine.cervix"                                 "adrenal.gland"                                 
[201] "stomach"                                        "cerebellum"                                    
[203] "brain.stem"                                     "frontal.lobe"                                  
[205] "corpus.striatum"                                "occipital.lobe"                                
[207] "parietal.lobe"                                  "brain"                                         
dim(data)
[1] 2656  208
head(data)
NA

Convert to long format

data_long <- melt(data, id.vars=c("Name", "Seq", "Canonical", "Source"))

Binarization

data_long <- data_long[!is.na(data_long$value),]
data_long$Binary <- sapply(data_long$value, function(x) if (x == 0) return(0) else return(1))
names(data_long) <- c("miR", "Seq", "Canonical", "Source", "Tissue", "Scale", "Binary")

Write to file

write.table(data_long, paste(sep="", result_path,"/lorenzi_longData.txt"), sep = "\t", row.names = F, col.names = T, quote = F)
write.table(unique(data_long[,1:3]), paste(sep="", result_path,"/lorenzi_miRNAs.txt"), sep = "\t", row.names = F, col.names = T, quote = F)
writeLines(as.character(unique(data_long$Tissue)), paste(sep="", result_path,"/lorenzi_tissues.txt"))
LS0tCnRpdGxlOiAiUHJvY2Vzc2luZyBsb3JlbnppIGV4cHJlc3Npb24gZGF0YSIKYXV0aG9yOiAiWnVoYWliIEFobWVkLCBHaXR0YSBFa2FwdXRlcmksIEFubmUtQ2hyaXN0aW4gSGF1c2NoaWxkIgpkYXRlOiAiMjkvMDgvMjAyMiIgCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkobWlSQmFzZUNvbnZlcnRlcikKbGlicmFyeShyZXNoYXBlMikKCnJvb3RfcGF0aCA8LSAiLi4vIgojIyBEZWZpbmUgU3RhbmRhcmQgZm9sZGVycwpnZW5lcmFsZGF0YV9wYXRoIDwtIHBhc3RlKHJvb3RfcGF0aCwgIi9zb3VyY2UiLCBzZXA9IiIpCmRhdGFfcGF0aCA8LSBwYXN0ZShyb290X3BhdGgsICJkYXRhL21pUk5BL2xvcmVuemlEYXRhIiwgc2VwPSIiKQpyZXN1bHRfcGF0aCA8LSBwYXN0ZShyb290X3BhdGgsICJkYXRhL21pUk5BX2ZpbmFsIiwgc2VwPSIiKQptaXJiYXNlRmlsZTwtIHBhc3RlKHJvb3RfcGF0aCwgImRhdGEvbWlyYmFzZS9tYXR1cmVfaG9tby1zYXBpZW5zX2RhdGFmcmFtZS50eHQiLCBzZXA9IiIpCgpzZXR3ZChyb290X3BhdGgpCmBgYAoKIyMjIFJlYWQgY291bnRzIGRhdGEKCkxvYWQgYW5kIHRyYW5zcG9zZSBjb3VudHMgZmlsZSAoU2FtcGxlIElEcyBhcyBoZWFkZXIgYW5kIG1pUk5BIElEcyBhcyBmaXJzdCBjb2x1bW4pCmBgYHtyfQpvcmlDb3VudHNGaWxlIDwtIHJlYWQuY3N2KGZpbGUgPSBwYXN0ZShzZXA9IiIsIGRhdGFfcGF0aCwnL21hdHVyZV9jb3VudHNfYWxsLmNzdicpKQpjb3VudHNGaWxlIDwtIGFzLmRhdGEuZnJhbWUodChvcmlDb3VudHNGaWxlKSkgIyB0cmFuc3Bvc2Ugb3JpQ291bnRzRmlsZQpjb3VudHNGaWxlIDwtIGphbml0b3I6OnJvd190b19uYW1lcyhjb3VudHNGaWxlLCByb3dfbnVtYmVyPTEpCmNvdW50c0ZpbGUgPC0gdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oY291bnRzRmlsZSwgdmFyPSJtaVIiKQpjb3VudHNGaWxlJG1pUiA8LSBjaGFydHIoJy4nLCAnLScsIGNvdW50c0ZpbGUkbWlSKSAjIHJlcGxhY2UgJy4nIHdpdGggJy0nIGluIG1pUgpjb3VudHNGaWxlCmBgYAoKIyMjIFVwZGF0ZSB0aGUgSURzIAoKYGBge3J9CnVwZGF0ZSA8LSBtaVJOQVZlcnNpb25Db252ZXJ0KGNvdW50c0ZpbGUkbWlSKQpoZWFkKHVwZGF0ZSkKbGVuZ3RoKHVuaXF1ZShjb3VudHNGaWxlJG1pUikpCmxlbmd0aCh1bmlxdWUodXBkYXRlWywiT3JpZ2luYWxOYW1lIl0pKQpsZW5ndGgodW5pcXVlKHVwZGF0ZVssIlRhcmdldE5hbWUiXSkpCgpgYGAKCkZldGNoIHRoZSBtaXJiYXNlMjIgSURzIGFuZCBzZXF1ZW5jZXMKCmBgYHtyfQptcmJzZSA8LSByZWFkLnRhYmxlKG1pcmJhc2VGaWxlLCBoZWFkZXIgPSBULCBzZXAgPSAiXHQiKQptcmJzZSA8LSBtcmJzZVstYygxLDIpLF0gIyBUaGUgZmlyc3QgdHdvIHJvd3MgZG9uJ3QgbWF0Y2ggdXAgd2l0aCBtaXJiYXNlLCBhcmUgdGhlIG9ubHkgZHVwbGljYXRlcywgYW5kIGFyZSB0aGUgb25seSBzZXF1ZW5jZXMgd2l0aCBUJ3MgZm9yIHNvbWUgcmVhc29uLiBJJ2xsIHJlbW92ZSB0aGVtLgpkaW0obXJic2UpCmhlYWQobXJic2UpCmBgYAoKQ3JlYXRlIG1pY3JvUk5BIE1hcHBpbmcgdGFibGUgYW5kIFVwZGF0ZSBDb3VudGZpbGUgbWlSTkEgUm93IE5hbWVzCmBgYHtyfQptcmJzZTIgPC0gbWVyZ2UobXJic2UsIHVwZGF0ZSwgYnkueCA9IDEsIGJ5LnkgPSAyLCBhbGwueCA9IEYsIGFsbC55ID0gVCkKbXJic2UyIDwtIG1yYnNlMlssLTRdCmRpbShtcmJzZTIpCmhlYWQobXJic2UyKQpyb3duYW1lcyhtcmJzZTIpPC0gbXJic2UyWywiT3JpZ2luYWxOYW1lIl0Kcm93bmFtZXMoY291bnRzRmlsZSk8LWNvdW50c0ZpbGVbLDFdCnJvd25hbWVzKGNvdW50c0ZpbGUpPC0gbXJic2UyW3Jvd25hbWVzKGNvdW50c0ZpbGUpLCAiTmFtZSJdCmBgYAoKCkNyZWF0ZSBSb3cgZm9yIGVhY2ggbWlSTkEgYW5kIE1lcmdlIHRoaXMgd2l0aCB0aGUgZGF0YQoKYGBge3J9Cm1lcmdlZERhdGEgPC0gbWF0cml4KDAsIG5yb3cgPSBkaW0obXJic2UpWzFdLCBuY29sPSAzMDIpCm1lcmdlZERhdGEgPC0gZGF0YS5mcmFtZShtZXJnZWREYXRhKQptZXJnZWREYXRhPC0gY2JpbmQobXJic2UsIG1lcmdlZERhdGEpCmNvbG5hbWVzKG1lcmdlZERhdGEpPC0gYygiTmFtZSIsICJTZXEiLCBjb2xuYW1lcyhjb3VudHNGaWxlKVstMV0pCnJvd25hbWVzKG1lcmdlZERhdGEpPC1tZXJnZURhdGFbLDFdCm1lcmdlZERhdGFbcm93bmFtZXMoY291bnRzRmlsZSksIGNvbG5hbWVzKGNvdW50c0ZpbGUpWy0xXV08LSBjb3VudHNGaWxlWywtMV0KI21lcmdlZERhdGEgPC0gbWVyZ2UobXJic2UyLCBjb3VudHNGaWxlLCBieS54ID0gMywgYnkueSA9IDEsIGFsbC54ID0gVCwgYWxsLnkgPSBGKQpkaW0obWVyZ2VkRGF0YSkKaGVhZChtZXJnZWREYXRhKQojbWVyZ2VkRGF0YSA8LSBtZXJnZWREYXRhWywtMV0gIyBSZW1vdmUgdGhlIG9yaWdpbmFsIChvbGQpIElEcwptZXJnZWREYXRhWzE6NSwxOjVdCm1lcmdlZERhdGEKCmBgYAoKCiMjIyBRdWludGl6ZSB0aGUgZGF0YQoKRm9yIGVhY2ggY29sdW1uOiBhc3NpZ24gZWFjaCBtaVJOQSBhIHZhbHVlIDEtNSBkZXBlbmRpbmcgb24gd2hpY2ggb2YgdGhlIDIwdGggcGVyY2VudGlsZXMgaXQgZmFsbHMgaW50by4gSWYgdGhlIHZhbHVlIGlzIDAsIGl0IHJlbWFpbnMgYSAwCgpgYGB7cn0KIyBHaXZlbiBhIGNvbHVtbiwgYXNzaWduIGEgbnVtYmVyIHRvIGVhY2ggZWxlbWVudCBmcm9tIDAtNS4gQWxsCiMgMHMgZ2V0IGEgMCwgYW5kIHRoZSByZXN0IGdldCBhIHZhbHVlIGFjY29yZGluZyB0byB0aGUgMjB0aCBwZXJjZW50aWxlCiMgdGhhdCBpdCBmYWxscyBpbiBhbW9uZyB0aGUgbm9uLXplcm8gdmFsdWVzLgpxdWludGl6ZSA8LSBmdW5jdGlvbih2ZWMpIHsKICBxbnRscyA8LSBjKDAsIHF1YW50aWxlKHZlY1t3aGljaCh2ZWMgIT0gMCldLCAwLjIqKDE6NCkpKQogIHZlYzIgPC0gc2FwcGx5KHZlYywgZnVuY3Rpb24oeCkgewogICAgaWYgKHggPT0gMCkgcmV0dXJuKDApCiAgICBlbHNlIHJldHVybihtYXgod2hpY2goeCA+IHFudGxzKSkpCiAgfSkKICByZXR1cm4odmVjMikKfQpgYGAKCmBgYHtyfQptZXJnZWREYXRhWywzOm5jb2wobWVyZ2VkRGF0YSldID0gbGFwcGx5KG1lcmdlZERhdGFbLDM6bmNvbChtZXJnZWREYXRhKV0sIEZVTiA9IGZ1bmN0aW9uKHkpe2FzLm51bWVyaWMoeSl9KQpkaW0obWVyZ2VkRGF0YSkKcXVpbnRpemVkRGF0YSA8LSBhcHBseShtZXJnZWREYXRhWywtYygxOjIpXSwgMiwgcXVpbnRpemUpCnF1aW50aXplZERhdGEgPC0gY2JpbmQobWVyZ2VkRGF0YVssMToyXSwgcXVpbnRpemVkRGF0YSkKcXVpbnRpemVkRGF0YVsxOjUsMTo1XQpkaW0ocXVpbnRpemVkRGF0YSkKYGBgCgojIyMgQ29tYmluZSB0aGUgcmVwbGljYXRlcwoKR2V0IHRoZSBtZXRhIGluZm9ybWF0aW9uCgpgYGB7cn0KbWV0YSA8LSByZWFkLnRhYmxlKHBhc3RlKHNlcD0iIiwgZGF0YV9wYXRoLCIvbWV0YV9jZWxsdHlwZV90aXNzdWVfc1JOQS50eHQiKSwgaGVhZGVyID0gVCwgc2VwID0gIlx0IikKbWV0YSRTYW1wbGVfSUQgPC0gZ3N1YigiQmlvU2FtcGxlOiBodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2Jpb3NhbXBsZS8iLCAiIiwgbWV0YSRYLlNhbXBsZV9yZWxhdGlvbikgIyBleHRyYWN0IG9ubHkgU0FNTiBJRHMgZnJvbSBYLlNhbXBsZV9yZWxhdGlvbgptZXRhCmBgYAoKCkNyZWF0ZSBEaXNlYXNlLCBUaXNzdWUsIGFuZCBHcm91cCAoVGlzc3VlX0Rpc2Vhc2UpIGNvbHVtbnMKCmBgYHtyfQptZXRhJFRpc3N1ZSA8LSBzdHJfcmVwbGFjZV9hbGwobWV0YSRYLlNhbXBsZV9zb3VyY2VfbmFtZV9jaDEsICIgdGlzc3VlIiwgIiIpCm1ldGEkVGlzc3VlIDwtIHN0cl9yZXBsYWNlX2FsbChtZXRhJFRpc3N1ZSwgIlteQS1aYS16MC05XSsiLCAiXFwuIikKbWV0YSRUaXNzdWUgPC0gc3RyX3JlcGxhY2VfYWxsKG1ldGEkVGlzc3VlLCAiXFwuZG9ub3JcXC5bMC05XSsiLCAiIikKbWV0YSRUaXNzdWUgPC0gc3RyX3JlcGxhY2VfYWxsKG1ldGEkVGlzc3VlLCAiLSIsICIuIikKbWV0YSRUaXNzdWUgPC0gc3RyX3JlcGxhY2VfYWxsKG1ldGEkVGlzc3VlLCAiICIsICIuIikKbWV0YSRUaXNzdWUgPC0gdG9sb3dlcihtZXRhJFRpc3N1ZSkKbWV0YSRUaXNzdWUgPC0gc3RyX3JlcGxhY2VfYWxsKG1ldGEkVGlzc3VlLCAiY2IuY2QzNC5saW4uIiwgImNiLmNkMzQubGluIikKbWV0YSREaXNlYXNlIDwtICIiICNhbGwgbm9ybWFsCm1ldGEkR3JvdXAgPC0gYXBwbHkobWV0YVssYyhuY29sKG1ldGEpLTEsbmNvbChtZXRhKSldLCAxLCBmdW5jdGlvbih4KSBwYXN0ZSh4WzFdLCB4WzJdLCBzZXA9Il8iKSkKbWV0YSRHcm91cCA8LSBzdHJfcmVwbGFjZV9hbGwobWV0YSRHcm91cCwgIl8iLCAiIikKaGVhZChtZXRhKQpgYGAKCgpHcm91cGluZzogQ29tYmluZSByZXBsaWNhdGVzIChzYW1wbGVzIHRoYXQgaGF2ZSB0aGUgc2FtZSB0eXBlKQoKYGBge3J9CnVuaXF1ZVRpc3N1ZXMgPC0gdW5pcXVlKG1ldGEkR3JvdXApCm1ldGEkU2FtcGxlX0lEICVpbiUgbmFtZXMocXVpbnRpemVkRGF0YSkKbWV0YSA8LSBtZXRhWyEobWV0YSRTYW1wbGVfSUQgPT0gIlNBTU4xMzAxNDIzNiIpLF0gIyBTYW1wbGUgZG9lcyBub3QgZXhpc3QgaW4gY291bnRzIGZpbGUKCiMgUmVtb3ZlIGNvbHVtbnMgaW4gcXVpbnRpemVkRGF0YSB0aGF0IGRvZXMgbm90IGV4aXN0IGluIG1ldGEgKHRoYXQgbWVhbnMgdGhlIHNhbXBsZSB0eXBlIGlzIG5vdCB0aXNzdWUgYW5kIG5vdCBjZWxsIHR5cGUpCm5hbWVzKHF1aW50aXplZERhdGEpICVpbiUgbWV0YSRTYW1wbGVfSUQKcXVpbnRpemVkRGF0YTIgPC0gcXVpbnRpemVkRGF0YVssY29sbmFtZXMocXVpbnRpemVkRGF0YSkgJWluJSBtZXRhJFNhbXBsZV9JRF0KCiMgQWRkIE5hbWUgYW5kIFNlcSBjb2x1bW5zCnF1aW50aXplZERhdGEyIDwtIGNiaW5kKHF1aW50aXplZERhdGFbLDE6Ml0sIHF1aW50aXplZERhdGEyKQoKCiNxdWludGl6ZWREYXRhMiA8LSBjYmluZChxdWludGl6ZWREYXRhJFNlcSxxdWludGl6ZWREYXRhMikKI3F1aW50aXplZERhdGEyIDwtIGNiaW5kKHF1aW50aXplZERhdGEkTmFtZSxxdWludGl6ZWREYXRhMikKI25hbWVzKHF1aW50aXplZERhdGEyKVsxXSA8LSAiTmFtZSIKI25hbWVzKHF1aW50aXplZERhdGEyKVsyXSA8LSAiU2VxIgojbmFtZXMocXVpbnRpemVkRGF0YTIpICVpbiUgbWV0YSRTYW1wbGVfSUQKCgoKCmNvbWJpbmVkRGF0YSA8LSBsYXBwbHkodW5pcXVlVGlzc3VlcywgZnVuY3Rpb24oeCkgewogIGRmIDwtIGFzLmRhdGEuZnJhbWUocXVpbnRpemVkRGF0YTJbLG1ldGEkU2FtcGxlX0lEW3doaWNoKG1ldGEkR3JvdXAgPT0geCldXSkKICByZXR1cm4ocm93TWVhbnMoZGYpKQp9KQpuYW1lcyhjb21iaW5lZERhdGEpIDwtIHVuaXF1ZVRpc3N1ZXMKY29tYmluZWREYXRhIDwtIGRvLmNhbGwoY2JpbmQsIGNvbWJpbmVkRGF0YSkKY29tYmluZWREYXRhIDwtIGNiaW5kKHF1aW50aXplZERhdGEyWywxOjJdLCBjb21iaW5lZERhdGEpCmRpbShjb21iaW5lZERhdGEpCmBgYAoKCiMjIyBFbnN1cmUgdGhlIHRlcm1zIGFyZSBzdGFuZGFyZGl6ZWQKRW5zdXJlIHRoYXQgYWxsIHRoZSBncm91cCBuYW1lcyBhcHBlYXIgaW4gdGhlIG9udG9sb2d5IG9yIHRoZSBjb3JyZWN0aW9ucyBmaWxlLgoKR2V0IHRoZSBvbnRvbG9neSBhbmQgY29ycmVjdGlvbiBmaWxlcwoKYGBge3J9Cm9udCA8LSByZWFkLnRhYmxlKHBhc3RlKHNlcD0iIiwgZ2VuZXJhbGRhdGFfcGF0aCwiL29udG9sb2d5LnR4dCIpLCBoZWFkZXIgPSBGLCBzZXAgPSAiXHQiKQpjb3JyIDwtIHJlYWQudGFibGUocGFzdGUoc2VwPSIiLCBnZW5lcmFsZGF0YV9wYXRoLCIvY29ycmVjdGlvbnMudHh0IiksIGhlYWRlciA9IFQsIHNlcCA9ICJcdCIpCmhlYWQob250KQpgYGAKCkFpbSB0byBoYXZlIDAgYXMgYSByZXN1bHQsIG1lYW5pbmcgYWxsIHRlcm1zIGFyZSBlaXRoZXIgYWxyZWFkeSBpbiB0aGUgb250b2xvZ3kgb3IgdGhlIGNvcnJlY3Rpb24gZmlsZS4gT3IgZWxzZTogdXBkYXRlIGNvcnJlY3Rpb24gZmlsZSBvciBvbnRvbG9neSBmaWxlLCBvciBib3RoLgoKYGBge3J9CnRybXMgPC0gdW5pcXVlKHVubGlzdChzdHJzcGxpdChuYW1lcyhjb21iaW5lZERhdGEpWzM6bmNvbChjb21iaW5lZERhdGEpXSwgIl8iKSkpICMgU3BsaXRzIHRoZSBjb21wb3NpdGUgdGVybXMgdGhhdCBjb250YWluIGJvdGggdGlzc3VlK2Rpc2Vhc2UKaWYgKGxlbmd0aCh3aGljaCh0cm1zICVpbiUgdW5pb24oY29yclssMV0sIHVuaXF1ZSh1bmxpc3Qob250WyxjKDEsMyldKSkpKSkgIT0gMCl7CiAgdHJtc1std2hpY2godHJtcyAlaW4lIHVuaW9uKGNvcnJbLDFdLCB1bmlxdWUodW5saXN0KG9udFssYygxLDMpXSkpKSldICMgV2hpY2ggdGVybXMgYXJlbid0IGluIHRoZSBvbnRvbG9neSBvciB0aGUgY29ycmVjdGVkIHRlcm1zCn0gZWxzZSB7CiAgdHJtcwp9CmBgYAoKQ29ycmVjdCBjdXJyZW50IHRlcm1zIHRoYXQgbmVlZCB0byBiZSBjb3JyZWN0ZWQuCmBgYHtyfQpjb2xuYW1lcyhjb21iaW5lZERhdGEpIDwtIHNhcHBseShjb2xuYW1lcyhjb21iaW5lZERhdGEpLCBmdW5jdGlvbih6KSB7CiAgeSA8LSBzdHJzcGxpdCh6LCAiXyIpW1sxXV0KICByZXRWYWwgPC0gc2FwcGx5KHksIGZ1bmN0aW9uKHgpIHsKICAgIGlmICh4ICVpbiUgY29yciRjdXJyZW50VGVybSkgewogICAgICByZXR1cm4oY29yciRjb3JyZWN0ZWRUZXJtW21hdGNoKHgsIGNvcnIkY3VycmVudFRlcm0pXSkKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybih4KQogICAgfQogIH0pCiAgcmV0dXJuKHBhc3RlKHJldFZhbCwgY29sbGFwc2UgPSAiXyIpKQp9KQpkaW0oY29tYmluZWREYXRhKQpoZWFkKGNvbWJpbmVkRGF0YSkKYGBgCgojIyMgQ29udmVydCB0byBsb25nIGZvcm1hdApBZGQgdGhlIENhbm9uaWNhbCBjb2x1bW4gYW5kIFNvdXJjZSBjb2x1bW4KCmBgYHtyfQpuPC1kaW0oY29tYmluZWREYXRhKVsxXQpkYXRhPC0gY2JpbmQoY29tYmluZWREYXRhWyJOYW1lIl0sY29tYmluZWREYXRhWyJTZXEiXSxDYW5vbmljYWw9cmVwKFQsIG4pICwgU291cmNlPXJlcCgiTG9yZW56aSoiLCBuKSAsIGNvbWJpbmVkRGF0YVssMzpkaW0oY29tYmluZWREYXRhKVsyXSBdKQpjb2xuYW1lcyhkYXRhKTwtIGMoIk5hbWUiLCAiU2VxIiwgIkNhbm9uaWNhbCIsICJTb3VyY2UiLCBjb2xuYW1lcyhjb21iaW5lZERhdGEpWy1jKDEsMildKQpjb2xuYW1lcyhkYXRhKQpkaW0oZGF0YSkKaGVhZChkYXRhKQoKYGBgCgoKQ29udmVydCB0byBsb25nIGZvcm1hdAoKYGBge3J9CmRhdGFfbG9uZyA8LSBtZWx0KGRhdGEsIGlkLnZhcnM9YygiTmFtZSIsICJTZXEiLCAiQ2Fub25pY2FsIiwgIlNvdXJjZSIpKQpgYGAKCkJpbmFyaXphdGlvbgpgYGB7cn0KZGF0YV9sb25nIDwtIGRhdGFfbG9uZ1shaXMubmEoZGF0YV9sb25nJHZhbHVlKSxdCmRhdGFfbG9uZyRCaW5hcnkgPC0gc2FwcGx5KGRhdGFfbG9uZyR2YWx1ZSwgZnVuY3Rpb24oeCkgaWYgKHggPT0gMCkgcmV0dXJuKDApIGVsc2UgcmV0dXJuKDEpKQpuYW1lcyhkYXRhX2xvbmcpIDwtIGMoIm1pUiIsICJTZXEiLCAiQ2Fub25pY2FsIiwgIlNvdXJjZSIsICJUaXNzdWUiLCAiU2NhbGUiLCAiQmluYXJ5IikKYGBgCgojIyMgV3JpdGUgdG8gZmlsZQoKYGBge3J9CndyaXRlLnRhYmxlKGRhdGFfbG9uZywgcGFzdGUoc2VwPSIiLCByZXN1bHRfcGF0aCwiL2xvcmVuemlfbG9uZ0RhdGEudHh0IiksIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQsIHF1b3RlID0gRikKd3JpdGUudGFibGUodW5pcXVlKGRhdGFfbG9uZ1ssMTozXSksIHBhc3RlKHNlcD0iIiwgcmVzdWx0X3BhdGgsIi9sb3JlbnppX21pUk5Bcy50eHQiKSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gVCwgcXVvdGUgPSBGKQp3cml0ZUxpbmVzKGFzLmNoYXJhY3Rlcih1bmlxdWUoZGF0YV9sb25nJFRpc3N1ZSkpLCBwYXN0ZShzZXA9IiIsIHJlc3VsdF9wYXRoLCIvbG9yZW56aV90aXNzdWVzLnR4dCIpKQpgYGA=